﻿using System;
using System.Collections.Generic;

namespace LastLand.Data.World
{
    public class CWorld
    {
        private Int32 width_;
        private Int32 height_;

        private List<List<CWorldGrid>> worldGrid_;   //地图格
        private List<CCountry> country_;             //国家
        private List<CCity> city_;                   //城市
        private List<CCharacter> character_;         //玩家角色
        private List<CCombat> combat_;               //战斗

        public CWorld()
        {
        }

        public void CreateNewWorld(Int32 _width, Int32 _height)
        {
            width_ = _width;
            height_ = _height;

            worldGrid_ = new List<List<CWorldGrid>>();
            for (Int32 i = 0; i < _width; i++)
            {
                List<CWorldGrid> row = new List<CWorldGrid>();
                for (Int32 j = 0; j < _height; j++)
                {
                    row.Add(new CWorldGrid(i, j));
                }
                worldGrid_.Add(row);
            }

            country_ = new List<CCountry>();
            city_ = new List<CCity>();
            character_ = new List<CCharacter>();
            combat_ = new List<CCombat>();
        }

        public void UpdateWorld()
        {
            for (Int32 i = 0; i < width_; i++)
            {
                for (Int32 j = 0; j < height_; j++)
                {
                    CWorldGrid position = worldGrid_[i][j];
                    position.Food += position.FoodProdRate + position.FarmLevel;
                    position.Hammer += position.HammerProdRate + position.MineLevel;
                    position.Gold += position.GoldProdRate + position.VillageLevel;
                    CCity city = position.City;
                    Int32 foodLimit = city != null ? position.FoodLimit + city.GranaryLevel : position.FoodLimit;
                    Int32 hammerLimit = city != null ? position.HammerLimit + city.ForgeLevel : position.HammerLimit;
                    Int32 goldLimit = city != null ? position.GoldLimit + city.MarketLevel : position.GoldLimit;
                    if (position.Food > foodLimit)
                    {
                        if (position.Country != null)
                        {
                            position.Country.Food += position.Food - foodLimit;
                        }
                        position.Food = foodLimit;
                    }
                    if (position.Hammer > hammerLimit)
                    {
                        position.Hammer = hammerLimit;
                    }
                    if (position.Gold > goldLimit)
                    {
                        position.Gold = goldLimit;
                    }
                }
            }
        }

        public void UpdateCombat()
        {
            List<CCombat> removeCombat = new List<CCombat>();
            for (Int32 i = 0; i < combat_.Count; i++)
            {
                CCombat combat = combat_[i];
                Random rand = new Random();
                for (Int32 j = 0; j < combat.Attacker.Count; j++)
                {
                    CCharacter attacker = combat.Attacker[j];

                    if (combat.HP <= combat.HPLimit)
                    {
                        if (combat.Defender.Count > 0)
                        {
                            CCharacter defender = combat.Defender[rand.Next(combat.Defender.Count)];
                            defender.HP -= attacker.MeleeAttack + attacker.RangedAttack + attacker.MeleeLevel + attacker.RangedLevel - defender.Armor - defender.Shield - defender.ArmorLevel - defender.ShieldLevel;
                        }
                        combat.HP -= attacker.MeleeAttack + attacker.MeleeLevel + (attacker.SiegeAttack + attacker.SiegeLevel) * 10;
                    }
                    else
                    {
                        combat.HP -= attacker.MeleeAttack + attacker.MeleeLevel + (attacker.SiegeAttack + attacker.SiegeLevel) * 10;
                    }
                }

                if (combat.Attacker.Count > 0)
                {
                    for (Int32 j = 0; j < combat.Defender.Count; j++)
                    {
                        CCharacter attacker = combat.Attacker[rand.Next(combat.Attacker.Count)];
                        CCharacter defender = combat.Defender[j];
                        if (combat.HP <= combat.HPLimit)
                        {
                            attacker.HP -= defender.MeleeAttack + defender.RangedAttack + defender.MeleeLevel + defender.RangedLevel - attacker.Armor - attacker.Shield - attacker.ArmorLevel - attacker.ShieldLevel;
                        }
                        else
                        {
                            attacker.HP -= defender.RangedAttack + defender.RangedLevel - attacker.Shield - attacker.ShieldLevel;
                        }
                    }
                }

                List<CCharacter> removeCharacter = new List<CCharacter>();
                for (Int32 j = 0; j < combat.Attacker.Count; j++)
                {
                    CCharacter attacker = combat.Attacker[j];
                    if (attacker.HP <= 0)
                    {
                        removeCharacter.Add(attacker);
                    }
                }
                foreach (CCharacter attacker in removeCharacter)
                {
                    attacker.Combat = null;
                    attacker.Country.Population--;
                    combat.Attacker.Remove(attacker);
                }
                removeCharacter.Clear();
                for (Int32 j = 0; j < combat.Defender.Count; j++)
                {
                    CCharacter defender = combat.Defender[j];
                    if (defender.HP <= 0)
                    {
                        removeCharacter.Add(defender);
                    }
                }
                foreach (CCharacter defender in removeCharacter)
                {
                    defender.Combat = null;
                    defender.Country.Population--;
                    combat.Defender.Remove(defender);
                }
                removeCharacter.Clear();

                if (combat.HP <= 0)
                {
                    foreach (CCharacter attacker in combat.Attacker)
                    {
                        attacker.Combat = null;
                    }
                    foreach (CCharacter defender in combat.Defender)
                    {
                        defender.Combat = null;
                    }
                    combat.Position.Combat = null;
                    removeCombat.Add(combat);

                    if (combat.Position.CityLevel > 0)
                    {
                        CCountry country = combat.Position.Country;
                        CCity city = combat.Position.City;
                        for (Int32 j = 0; j < width_; j++)
                        {
                            for (Int32 k = 0; k < height_; k++)
                            {
                                CWorldGrid position = worldGrid_[j][k];
                                if (position.City == city)
                                {                                    
                                    country.TerritoryGrid.Remove(position);                                    
                                    position.City = null;
                                    position.Country = null;
                                }
                            }
                        }                        
                        country.City.Remove(city);
                        city_.Remove(city);
                        combat.Position.CityLevel = 0;
                        if (country.TerritoryGrid.Count == 0)
                        {
                            foreach (CCharacter character in country.Character)
                            {
                                character.HP = 0;
                            }
                            country_.Remove(country);
                        }
                    }

                    combat.Position.FarmLevel = 0;
                    combat.Position.MineLevel = 0;
                    combat.Position.VillageLevel = 0;
                    combat.Position.FortLevel = 0;
                }

                if (combat.Attacker.Count == 0)
                {
                    foreach (CCharacter defender in combat.Defender)
                    {
                        defender.Combat = null;
                    }
                    combat.Position.Combat = null;
                    removeCombat.Add(combat);
                }
            }
            foreach (CCombat combat in removeCombat)
            {
                combat_.Remove(combat);
            }
            removeCombat.Clear();
        }

        public void UpdateCharacter()
        {
            for (Int32 i = 0; i < character_.Count; i++)
            {
                CCharacter character = character_[i];
                Int32 hpMax = 3 + character.HorseLevel;
                if (character.HP > 0 && character.HP < hpMax) character.HP++;
            }
        }

        public Int32 CreateNormalCharacter()
        {
            if (country_.Count == 0) return -1;

            List<CCountry> countryPool = new List<CCountry>();
            for (Int32 i = 0; i < country_.Count; i++)
            {
                CCountry tmpCountry = country_[i];
                if (tmpCountry.TerritoryGrid.Count > 0 && tmpCountry.Food >= tmpCountry.Population * 50) countryPool.Add(tmpCountry);
            }
            if (countryPool.Count == 0) return -1;

            Random rand = new Random();
            CCountry country = countryPool[rand.Next(0, countryPool.Count)];
            CCharacter character = new CCharacter();
            character_.Add(character);
            country.Food -= country.Population * 50;
            country.Population++;
            country.Character.Add(character);
            character.Country = country;
            character.Position = country.City[0].Position;

            return character_.Count - 1;
        }

        public Int32 CreateLeaderCharacter()
        {
            List<CWorldGrid> gridPool = new List<CWorldGrid>();
            for (Int32 i = 0; i < width_; i++)
            {
                for (Int32 j = 0; j < height_; j++)
                {
                    if (!worldGrid_[i][j].IsTerritory()) gridPool.Add(worldGrid_[i][j]);
                }
            }
            if (gridPool.Count == 0) return -1;

            Random rand = new Random();
            CWorldGrid position = gridPool[rand.Next(0, gridPool.Count)];
            CCountry country = new CCountry();
            CCity city = new CCity();
            city_.Add(city);
            city.Position = position;
            city.Territory.Add(position);
            position.City = city;
            position.Country = country;
            position.CityLevel++;
            country.City.Add(city);
            city.Country = country;
            country.TerritoryGrid.AddRange(city.Territory);
            country_.Add(country);
            CCharacter character = new CCharacter();
            character_.Add(character);
            //country.Food -= country.Population * 100;
            country.Population++;
            country.Character.Add(character);
            character.Country = country;
            character.Position = country.City[0].Position;

            return character_.Count - 1;
        }

        public void MoveEast(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null)
            {
                Int32 posX = character.Position.PosX;
                Int32 posY = character.Position.PosY;
                posX++;
                if (posX == width_) posX = 0;
                character.Position = worldGrid_[posX][posY];
            }
        }

        public void MoveSouth(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null)
            {
                Int32 posX = character.Position.PosX;
                Int32 posY = character.Position.PosY;
                posY++;
                if (posY == height_) posY = 0;
                character.Position = worldGrid_[posX][posY];
            }
        }

        public void MoveWest(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null)
            {
                Int32 posX = character.Position.PosX;
                Int32 posY = character.Position.PosY;
                posX--;
                if (posX == -1) posX = width_ - 1;
                character.Position = worldGrid_[posX][posY];
            }
        }

        public void MoveNorth(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null)
            {
                Int32 posX = character.Position.PosX;
                Int32 posY = character.Position.PosY;
                posY--;
                if (posY == -1) posY = height_ - 1;
                character.Position = worldGrid_[posX][posY];
            }
        }

        public List<Int32> Talk(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0)
            {
                CWorldGrid position = character.Position;
                CCountry country = position.Country;

                List<Int32> characterList = new List<Int32>();
                for (Int32 i = 0; i < character_.Count; i++)
                {
                    if (country == null)
                    {
                        if (character_[i].Position == position && character_[i] != character)
                        {
                            characterList.Add(i);
                        }
                    }
                    else
                    {
                        if (character_[i].Position.Country == country && character_[i] != character)
                        {
                            characterList.Add(i);
                        }
                    }
                }

                return characterList;
            }
            return null;
        }

        public void Collect(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && (character.Position.Country == null || character.Position.Country == character.Country))
            {
                character.Country.Food += character.Position.Food;
                character.Hammer += character.Position.Hammer;
                character.Gold += character.Position.Gold;

                character.Position.Food = 0;
                character.Position.Hammer = 0;
                character.Position.Gold = 0;
            }
        }

        public void BuyMeleeWeapon(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.MeleeTechLevel >= character.MeleeLevel)
            {
                Int32 meleeLevel = character.MeleeLevel;
                if (character.Gold >= meleeLevel * 10 + 20)
                {
                    character.Gold -= meleeLevel * 10 + 20;
                    character.MeleeLevel++;
                }
            }
        }

        public void BuyRangedWeapon(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.RangedTechLevel >= character.RangedLevel)
            {
                Int32 rangedLevel = character.RangedLevel;
                if (character.Gold >= rangedLevel * 10 + 20)
                {
                    character.Gold -= rangedLevel * 10 + 20;
                    character.RangedLevel++;
                }
            }
        }

        public void BuySiegeWeapon(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.SiegeTechLevel >= character.SiegeLevel)
            {
                Int32 siegeLevel = character.SiegeLevel;
                if (character.Gold >= siegeLevel * 10 + 20)
                {
                    character.Gold -= siegeLevel * 10 + 20;
                    character.SiegeLevel++;
                }
            }
        }

        public void BuyHorse(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.MountedTechLevel >= character.HorseLevel)
            {
                Int32 horseLevel = character.HorseLevel;
                if (character.Gold >= horseLevel * 10 + 20)
                {
                    character.Gold -= horseLevel * 10 + 20;
                    character.HorseLevel++;
                }
            }
        }

        public void BuyArmor(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.MeleeTechLevel >= character.ArmorLevel)
            {
                Int32 armorLevel = character.ArmorLevel;
                if (character.Gold >= armorLevel * 10 + 20)
                {
                    character.Gold -= armorLevel * 10 + 20;
                    character.ArmorLevel++;
                }
            }
        }

        public void BuyShield(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country
                && character.Position.Country.RangedTechLevel >= character.ShieldLevel)
            {
                Int32 shieldLevel = character.ShieldLevel;
                if (character.Gold >= shieldLevel * 10 + 20)
                {
                    character.Gold -= shieldLevel * 10 + 20;
                    character.ShieldLevel++;
                }
            }
        }

        public void BuyMeleeTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.MeleeTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.MeleeTechProgress > 200)
                {
                    character.Country.MeleeTechProgress -= 200;
                    character.Country.MeleeTechLevel++;
                }
            }
        }

        public void BuyRangedTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.RangedTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.RangedTechProgress > 200)
                {
                    character.Country.RangedTechProgress -= 200;
                    character.Country.RangedTechLevel++;
                }
            }
        }

        public void BuyMountedTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.MountedTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.MountedTechProgress > 200)
                {
                    character.Country.MountedTechProgress -= 200;
                    character.Country.MountedTechLevel++;
                }
            }
        }

        public void BuySiegeTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.SiegeTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.SiegeTechProgress > 200)
                {
                    character.Country.SiegeTechProgress -= 200;
                    character.Country.SiegeTechLevel++;
                }
            }
        }

        public void BuyAgricultureTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.AgricultureTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.AgricultureTechProgress > 200)
                {
                    character.Country.AgricultureTechProgress -= 200;
                    character.Country.AgricultureTechLevel++;
                }
            }
        }

        public void BuyIndustryTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.IndustryTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.IndustryTechProgress > 200)
                {
                    character.Country.IndustryTechProgress -= 200;
                    character.Country.IndustryTechLevel++;
                }
            }
        }

        public void BuyCommerceTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.CommerceTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.CommerceTechProgress > 200)
                {
                    character.Country.CommerceTechProgress -= 200;
                    character.Country.CommerceTechLevel++;
                }
            }
        }

        public void BuyConstructionTech(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.CityLevel > 0
                && character.Position.Country == character.Country)
            {
                character.Country.ConstructionTechProgress += character.Gold;
                character.Gold = 0;
                while (character.Country.ConstructionTechProgress > 200)
                {
                    character.Country.ConstructionTechProgress -= 200;
                    character.Country.ConstructionTechLevel++;
                }
            }
        }

        public void BuildCity(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == null
                && character.Position.CityLevel == 0
                && character.Hammer >= 50)
            {
                CCity city = new CCity();
                CWorldGrid position = character.Position;
                CCountry country = character.Country;
                city_.Add(city);
                city.Position = position;
                city.Territory.Add(position);
                position.City = city;
                position.Country = country;
                position.FarmLevel = 0;
                position.MineLevel = 0;
                position.VillageLevel = 0;
                position.FortLevel = 0;
                position.CityLevel++;
                country.City.Add(city);
                city.Country = country;
                country.TerritoryGrid.AddRange(city.Territory);
                character.Hammer -= 200;
            }
        }

        public void BuildFarm(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel == 0
                && character.Position.Country.AgricultureTechLevel >= character.Position.FarmLevel)
            {
                if (character.Position.FarmLevel == 0 && character.Hammer >= 20)
                {
                    CWorldGrid position = character.Position;
                    position.MineLevel = 0;
                    position.VillageLevel = 0;
                    position.FortLevel = 0;
                    position.CityLevel = 0;
                    position.FarmLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.FarmLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.FarmLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildMine(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel == 0
                && character.Position.Country.IndustryTechLevel >= character.Position.MineLevel)
            {
                if (character.Position.MineLevel == 0 && character.Hammer >= 20)
                {
                    CWorldGrid position = character.Position;
                    position.FarmLevel = 0;
                    position.VillageLevel = 0;
                    position.FortLevel = 0;
                    position.CityLevel = 0;
                    position.MineLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.MineLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.MineLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildVillage(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel == 0
                && character.Position.Country.CommerceTechLevel >= character.Position.VillageLevel)
            {
                if (character.Position.VillageLevel == 0 && character.Hammer >= 20)
                {
                    CWorldGrid position = character.Position;
                    position.FarmLevel = 0;
                    position.MineLevel = 0;
                    position.FortLevel = 0;
                    position.CityLevel = 0;
                    position.VillageLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.VillageLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.VillageLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildFort(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel == 0
                && character.Position.Country.ConstructionTechLevel >= character.Position.FortLevel)
            {
                if (character.Position.FortLevel == 0 && character.Hammer >= 50)
                {
                    CWorldGrid position = character.Position;
                    position.FarmLevel = 0;
                    position.VillageLevel = 0;
                    position.MineLevel = 0;
                    position.CityLevel = 0;
                    position.FortLevel++;
                    character.Hammer -= 50;
                }
                else if (character.Position.FortLevel > 0 && character.Hammer >= 50)
                {
                    character.Position.FortLevel++;
                    character.Hammer -= 50;
                }
            }
        }

        public void BuildGranary(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel > 0
                && character.Position.Country.AgricultureTechLevel >= character.Position.City.GranaryLevel)
            {
                if (character.Position.City.GranaryLevel == 0 && character.Hammer >= 20)
                {
                    character.Position.City.GranaryLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.City.GranaryLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.City.GranaryLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildForge(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character .HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel > 0
                && character.Position.Country.IndustryTechLevel >= character.Position.City.ForgeLevel)
            {
                if (character.Position.City.ForgeLevel == 0 && character.Hammer >= 20)
                {
                    character.Position.City.ForgeLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.City.ForgeLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.City.ForgeLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildMarket(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel > 0
                && character.Position.Country.CommerceTechLevel >= character.Position.City.MarketLevel)
            {
                if (character.Position.City.MarketLevel == 0 && character.Hammer >= 20)
                {
                    character.Position.City.MarketLevel++;
                    character.Hammer -= 20;
                }
                else if (character.Position.City.MarketLevel > 0 && character.Hammer >= 10)
                {
                    character.Position.City.MarketLevel++;
                    character.Hammer -= 10;
                }
            }
        }

        public void BuildCourthouse(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Combat == null
                && character.Position.Country == character.Country
                && character.Position.CityLevel > 0
                && character.Position.Country.ConstructionTechLevel >= character.Position.City.CourthouseLevel)
            {
                if (character.Position.City.CourthouseLevel == 0 && character.Hammer >= 50)
                {
                    character.Position.City.CourthouseLevel++;
                    character.Hammer -= 50;

                    CWorldGrid position = character.Position;
                    for (Int32 i = 0; i < width_; i++)
                    {
                        for (Int32 j = 0; j < height_; j++)
                        {
                            Int32 distance = Math.Abs(position.PosX - i) + Math.Abs(position.PosY - j);
                            if (worldGrid_[i][j].Country == null
                                && (distance <= position.City.CourthouseLevel || distance >= width_ + height_ - position.City.CourthouseLevel))
                            {
                                position.City.Territory.Add(worldGrid_[i][j]);
                                position.Country.TerritoryGrid.Add(worldGrid_[i][j]);
                                worldGrid_[i][j].City = position.City;
                                worldGrid_[i][j].Country = position.Country;
                            }
                        }
                    }
                }
                else if (character.Position.City.CourthouseLevel > 0 && character.Hammer >= 5 * character.Position.City.Territory.Count)
                {
                    character.Position.City.CourthouseLevel++;
                    character.Hammer -= 5 * character.Position.City.Territory.Count;

                    CWorldGrid position = character.Position;
                    for (Int32 i = 0; i < width_; i++)
                    {
                        for (Int32 j = 0; j < height_; j++)
                        {
                            Int32 distance = Math.Abs(position.PosX - i) + Math.Abs(position.PosY - j);
                            if (worldGrid_[i][j].Country == null
                                && (distance <= position.City.CourthouseLevel || distance >= width_ + height_ - position.City.CourthouseLevel))
                            {
                                position.City.Territory.Add(worldGrid_[i][j]);
                                position.Country.TerritoryGrid.Add(worldGrid_[i][j]);
                                worldGrid_[i][j].City = position.City;
                                worldGrid_[i][j].Country = position.Country;
                            }
                        }
                    }
                }
            }
        }

        public void Attack(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Country != null
                && character.Position.Country != character.Country
                && (character.Position.CityLevel > 0
                    || character.Position.FarmLevel > 0
                    || character.Position.MineLevel > 0
                    || character.Position.VillageLevel > 0
                    || character.Position.FortLevel > 0))
            {
                if (character.Position.Combat == null)
                {
                    CCombat combat = new CCombat();
                    combat.Attacker.Add(character);
                    character.Combat = combat;
                    character.Position.Combat = combat;
                    combat.Position = character.Position;

                    if (character.Position.FarmLevel > 0)
                    {
                        combat.HP = 199 + character.Position.FarmLevel;
                    }
                    if (character.Position.MineLevel > 0)
                    {
                        combat.HP = 498 + character.Position.MineLevel * 2;
                    }
                    if (character.Position.VillageLevel > 0)
                    {
                        combat.HP = 295 + character.Position.VillageLevel * 5;
                    }
                    if (character.Position.FortLevel > 0)
                    {
                        combat.HP = 990 + character.Position.FortLevel * 10;
                    }
                    if (character.Position.CityLevel > 0)
                    {
                        combat.HP = 800;
                    }

                    CWorldGrid position = character.Position;
                    Int32 fortBonus = position.FortLevel;
                    for (Int32 i = 0; i < width_; i++)
                    {
                        for (Int32 j = 0; j < height_; j++)
                        {
                            Int32 distance = Math.Abs(position.PosX - i) + Math.Abs(position.PosY - j);
                            if (worldGrid_[i][j].FortLevel > fortBonus
                                && distance <= 2 || distance >= width_ + height_ - 2)
                            {
                                fortBonus = worldGrid_[i][j].FortLevel;
                            }
                        }
                    }
                    combat.HP += 90 + fortBonus * 10;
                    combat.HPLimit = combat.HP / 3;

                    combat_.Add(combat);
                }
                else
                {
                    character.Position.Combat.Attacker.Add(character);
                    character.Combat = character.Position.Combat;
                }
            }
        }

        public void Defend(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat == null
                && character.Position.Country != null
                && character.Position.Combat != null
                && (character.Position.CityLevel > 0
                    || character.Position.FarmLevel > 0
                    || character.Position.MineLevel > 0
                    || character.Position.VillageLevel > 0
                    || character.Position.FortLevel > 0))
            {
                character.Position.Combat.Defender.Add(character);
                character.Combat = character.Position.Combat;
            }
        }

        public void Retreat(Int32 _index)
        {
            CCharacter character = character_[_index];
            if (character.HP > 0
                && character.Combat != null)
            {
                character.Combat.Attacker.Remove(character);
                character.Combat.Defender.Remove(character);                

                if (character.Combat.Attacker.Count == 0)
                {
                    foreach (CCharacter defender in character.Combat.Defender)
                    {
                        defender.Combat = null;
                    }
                    character.Position.Combat = null;
                    combat_.Remove(character.Combat);
                }
                
                character.Combat = null;
            }
        }

        public Boolean IsCharacterDead(Int32 _index)
        {
            return _index == -1 || character_[_index].HP <= 0;
        }

        public Boolean IsCharacterInCombat(Int32 _index)
        {
            return character_[_index].Combat != null;
        }

        public Boolean IsGridHostileTerritory(Int32 _index)
        {
            return character_[_index].Position.Country != null
                && character_[_index].Position.Country != character_[_index].Country;
        }

        public Boolean IsGridInCombat(Int32 _index)
        {
            return character_[_index].Position.Combat != null;
        }

        public Boolean IsGridOccupied(Int32 _index)
        {
            return character_[_index].Position.Country != null;
        }

        public Boolean IsGridTerritory(Int32 _index)
        {
            return character_[_index].Position.Country != null
                && character_[_index].Position.Country == character_[_index].Country;
        }

        public Boolean GridHasCity(Int32 _index)
        {
            return character_[_index].Position.CityLevel > 0;
        }

        public Boolean GridHasFacilityOrCity(Int32 _index)
        {
            return character_[_index].Position.CityLevel > 0
                || character_[_index].Position.FarmLevel > 0
                || character_[_index].Position.MineLevel > 0
                || character_[_index].Position.VillageLevel > 0
                || character_[_index].Position.FortLevel > 0;
        }

        public Boolean IsAgricultureTechEnoughForFarm(Int32 _index)
        {
            return character_[_index].Country.AgricultureTechLevel >= character_[_index].Position.FarmLevel;
        }

        public Boolean IsAgricultureTechEnoughForGranary(Int32 _index)
        {
            return character_[_index].Country.AgricultureTechLevel >= character_[_index].Position.City.GranaryLevel;
        }

        public Boolean IsIndustryTechEnoughForMine(Int32 _index)
        {
            return character_[_index].Country.IndustryTechLevel >= character_[_index].Position.MineLevel;
        }

        public Boolean IsIndustryTechEnoughForForge(Int32 _index)
        {
            return character_[_index].Country.IndustryTechLevel >= character_[_index].Position.City.ForgeLevel;
        }

        public Boolean IsCommerceTechEnoughForVillage(Int32 _index)
        {
            return character_[_index].Country.CommerceTechLevel >= character_[_index].Position.VillageLevel;
        }

        public Boolean IsCommerceTechEnoughForMarket(Int32 _index)
        {
            return character_[_index].Country.CommerceTechLevel >= character_[_index].Position.City.MarketLevel;
        }

        public Boolean IsConstructionTechEnoughForFort(Int32 _index)
        {
            return character_[_index].Country.ConstructionTechLevel >= character_[_index].Position.FortLevel;
        }

        public Boolean IsConstructionTechEnoughForCourthouse(Int32 _index)
        {
            return character_[_index].Country.ConstructionTechLevel >= character_[_index].Position.City.CourthouseLevel;
        }

        public Boolean IsMeleeTechEnoughForMelee(Int32 _index)
        {
            return character_[_index].Country.MeleeTechLevel >= character_[_index].MeleeLevel;
        }

        public Boolean IsMeleeTechEnoughForArmor(Int32 _index)
        {
            return character_[_index].Country.MeleeTechLevel >= character_[_index].ArmorLevel;
        }

        public Boolean IsRangedTechEnoughForRanged(Int32 _index)
        {
            return character_[_index].Country.RangedTechLevel >= character_[_index].RangedLevel;
        }

        public Boolean IsRangedTechEnoughForShield(Int32 _index)
        {
            return character_[_index].Country.RangedTechLevel >= character_[_index].ShieldLevel;
        }

        public Boolean IsSiegeTechEnoughForSiege(Int32 _index)
        {
            return character_[_index].Country.SiegeTechLevel >= character_[_index].SiegeLevel;
        }

        public Boolean IsMountedTechEnoughForHorse(Int32 _index)
        {
            return character_[_index].Country.MountedTechLevel >= character_[_index].HorseLevel;
        }

        public Boolean IsHammerEnoughForFarm(Int32 _index)
        {
            if (character_[_index].Position.FarmLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForMine(Int32 _index)
        {
            if (character_[_index].Position.MineLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForVillage(Int32 _index)
        {
            if (character_[_index].Position.VillageLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForFort(Int32 _index)
        {
            if (character_[_index].Position.FortLevel == 0) return character_[_index].Hammer >= 20;
            else return character_[_index].Hammer >= 10;
        }

        public Boolean IsHammerEnoughForGranary(Int32 _index)
        {
            if (character_[_index].Position.City.GranaryLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForForge(Int32 _index)
        {
            if (character_[_index].Position.City.ForgeLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForMarket(Int32 _index)
        {
            if (character_[_index].Position.City.MarketLevel == 0) return character_[_index].Hammer >= 10;
            else return character_[_index].Hammer >= 5;
        }

        public Boolean IsHammerEnoughForCourthouse(Int32 _index)
        {
            if (character_[_index].Position.City.CourthouseLevel == 0) return character_[_index].Hammer >= 20;
            else return character_[_index].Hammer >= 5 * character_[_index].Position.City.Territory.Count;
        }

        public Boolean IsHammerEnoughForCity(Int32 _index)
        {
            return character_[_index].Hammer >= 50;
        }

        public Boolean IsGoldEnoughForMelee(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].MeleeLevel;
        }

        public Boolean IsGoldEnoughForRanged(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].RangedLevel;
        }

        public Boolean IsGoldEnoughForSiege(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].SiegeLevel;
        }

        public Boolean IsGoldEnoughForHorse(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].HorseLevel;
        }

        public Boolean IsGoldEnoughForArmor(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].ArmorLevel;
        }

        public Boolean IsGoldEnoughForShield(Int32 _index)
        {
            return character_[_index].Gold >= 10 + 5 * character_[_index].ShieldLevel;
        }

        public Int32 Width
        {
            get { return width_; }
        }

        public Int32 Height
        {
            get { return height_; }
        }

        public Int32 CountryCount
        {
            get { return country_.Count; }
        }

        public Int32 TerritoryCount
        {
            get
            {
                Int32 count = 0;
                foreach (List<CWorldGrid> row in worldGrid_)
                {
                    foreach (CWorldGrid grid in row)
                    {
                        if (grid.Country != null) count++;
                    }
                }
                return count;
            }
        }

        public String CharacterInfo(Int32 _index)
        {
            CCharacter character = character_[_index];
            Int32 hpmax = 3 + character.HorseLevel;
            Int32 meleeAttack = character.MeleeAttack + character.MeleeLevel;
            Int32 rangedAttack = character.RangedAttack + character.RangedLevel;
            Int32 siegeAttack = character.SiegeAttack + character.SiegeLevel;
            Int32 armor = character.Armor + character.ArmorLevel;
            Int32 shield = character.Shield + character.ShieldLevel;

            return "character\t"
                + character.HP.ToString() + "\t"
                + hpmax.ToString() + "\t"
                + meleeAttack.ToString() + "\t"
                + rangedAttack.ToString() + "\t"
                + siegeAttack.ToString() + "\t"
                + armor.ToString() + "\t"
                + shield.ToString() + "\t"
                + character.Hammer.ToString() + "\t"
                + character.Gold.ToString() + "\t"
                + character.MeleeLevel.ToString() + "\t"
                + character.RangedLevel.ToString() + "\t"
                + character.SiegeLevel.ToString() + "\t"
                + character.HorseLevel.ToString() + "\t"
                + character.ArmorLevel.ToString() + "\t"
                + character.ShieldLevel.ToString() + "\t";
        }

        public String GridInfo(Int32 _index)
        {
            CCharacter character = character_[_index];
            CWorldGrid position = character.Position;
            CCity city = position.City;
            Int32 isTerritory = position.Country != null ? 1 : 0;
            Int32 isHostileTerritory = position.Country != null && position.Country != character.Country ? 1 : 0;
            Int32 isGridInCombat = position.Combat != null ? 1 : 0;
            Int32 gridHasCity = position.CityLevel > 0 ? 1 : 0;
            Int32 food = position.Food;
            Int32 hammer = position.Hammer;
            Int32 gold = position.Gold;
            Int32 foodLimit = city != null ? position.FoodLimit + city.GranaryLevel : position.FoodLimit;
            Int32 hammerLimit = city != null ? position.HammerLimit + city.ForgeLevel : position.HammerLimit;
            Int32 goldLimit = city != null ? position.GoldLimit + city.MarketLevel : position.GoldLimit;
            Int32 farm = position.FarmLevel;
            Int32 mine = position.MineLevel;
            Int32 village = position.VillageLevel;
            Int32 fort = position.FortLevel;

            return "grid\t"
                + isTerritory.ToString() + "\t"
                + isHostileTerritory.ToString() + "\t"
                + isGridInCombat.ToString() + "\t"
                + gridHasCity.ToString() + "\t"
                + food.ToString() + "\t"
                + foodLimit.ToString() + "\t"
                + hammer.ToString() + "\t"
                + hammerLimit.ToString() + "\t"
                + gold.ToString() + "\t"
                + goldLimit.ToString() + "\t"
                + farm.ToString() + "\t"
                + mine.ToString() + "\t"
                + village.ToString() + "\t"
                + fort.ToString() + "\t";
        }

        public String CityInfo(Int32 _index)
        {
            CCharacter character = character_[_index];
            CWorldGrid position = character.Position;
            CCity city = position.City;

            if (city == null) return "city\t";

            Int32 isHostileCity = city.Country != character.Country ? 1 : 0;
            Int32 territoryCount = city.Territory.Count;
            Int32 granary = city.GranaryLevel;
            Int32 forge = city.ForgeLevel;
            Int32 market = city.MarketLevel;
            Int32 courthouse = city.CourthouseLevel;

            return "city\t"
                + isHostileCity.ToString() + "\t"
                + territoryCount.ToString() + "\t"
                + granary.ToString() + "\t"
                + forge.ToString() + "\t"
                + market.ToString() + "\t"
                + courthouse.ToString() + "\t";
        }

        public String CountryInfo(Int32 _index)
        {
            CCharacter character = character_[_index];
            CCountry country = character.Country;

            Int32 cityCount = country.City.Count;
            Int32 territoryCount = country.TerritoryGrid.Count;
            Int32 meleeTech = country.MeleeTechLevel;
            Int32 rangedTech = country.RangedTechLevel;
            Int32 siegeTech = country.SiegeTechLevel;
            Int32 mountedTech = country.MountedTechLevel;
            Int32 agricultureTech = country.AgricultureTechLevel;
            Int32 industryTech = country.IndustryTechLevel;
            Int32 commerceTech = country.CommerceTechLevel;
            Int32 constructionTech = country.ConstructionTechLevel;
            Int32 meleeProgress = country.MeleeTechProgress;
            Int32 rangedProgress = country.RangedTechProgress;
            Int32 siegeProgress = country.SiegeTechProgress;
            Int32 mountedProgress = country.MountedTechProgress;
            Int32 agricultureProgress = country.AgricultureTechProgress;
            Int32 industryProgress = country.IndustryTechProgress;
            Int32 commerceProgress = country.CommerceTechProgress;
            Int32 constructionProgress = country.ConstructionTechProgress;
            Int32 food = country.Food;
            Int32 population = country.Population;

            return "country\t"
                + cityCount.ToString() + "\t"
                + territoryCount.ToString() + "\t"
                + meleeTech.ToString() + "\t"
                + meleeProgress.ToString() + "\t"
                + rangedTech.ToString() + "\t"
                + rangedProgress.ToString() + "\t"
                + siegeTech.ToString() + "\t"
                + siegeProgress.ToString() + "\t"
                + mountedTech.ToString() + "\t"
                + mountedProgress.ToString() + "\t"
                + agricultureTech.ToString() + "\t"
                + agricultureProgress.ToString() + "\t"
                + industryTech.ToString() + "\t"
                + industryProgress.ToString() + "\t"
                + commerceTech.ToString() + "\t"
                + commerceProgress.ToString() + "\t"
                + constructionTech.ToString() + "\t"
                + constructionProgress.ToString() + "\t"
                + food.ToString() + "\t"
                + population.ToString() + "\t";                ;
        }

        public String CombatInfo(Int32 _index)
        {
            CCharacter character = character_[_index];
            CCombat combat = character.Combat;

            if (combat == null) return "combat\t";

            Int32 hp = combat.HP;
            Int32 hpLimit = combat.HPLimit;
            Int32 attackerCount = combat.Attacker.Count;
            Int32 defenderCount = combat.Defender.Count;

            return "combat\t"
                + hp.ToString() + "\t"
                + hpLimit.ToString() + "\t"
                + attackerCount.ToString() + "\t"
                + defenderCount.ToString() + "\t";
        }
    }
}
